package org.jeecg.common.util.pdf;

import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.RectangleReadOnly;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.printing.PDFPrintable;
import org.apache.pdfbox.printing.Scaling;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.jeecg.common.util.DateUtils;
import org.jeecgframework.poi.excel.annotation.Excel;

import javax.print.PrintService;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.standard.Sides;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

public class PrintPdfUtils {
    public static void main(String[] args) throws Exception {

        //String templateUrl2 = "D:/opt/"+"送货单 (10).xlsx";
        //
        ////将模版和要写入模版的值传入，转换成workbook
        //Workbook workbook = ExcelConvertPDF.outPutWorkbookByModel(  new HashMap(), templateUrl2, ExcelTypeEnum.XLSX);
        //List<Workbook> workbooks = new ArrayList();
        //workbooks.add(workbook);
        //设置导出的页面的大小
        RectangleReadOnly pageSize = new RectangleReadOnly(600.0F, 450.0F);
        //定义输出流 也可以支持web的httpRespone
        String pathOfPdf = "D:/opt/"+ "test6.pdf";
        //FileOutputStream fos = new FileOutputStream(pathOfPdf);
        //ExcelConvertPDF.ExcelConvertPDF(workbooks, fos, pageSize, ExcelTypeEnum.XLSX);

        File file = new File(pathOfPdf);
        String printerName = "Hewlett-Packard HP LaserJet Pro MFP M126nw";//打印机名包含字串
        JSONObject printObj=new JSONObject();
        printObj.put("printName",printerName);
        printObj.put("printDirectionItem","2");

        PDFprint(file,printObj);

    }

    /**
     * 实体转换成Workbook
     * @param pageList 数据集
     * @param objClass 实体
     * @return
     * @throws Exception
     */
    public static Workbook entity2Workbook(List<Object> pageList,Class objClass,JSONObject printConfigObj)throws Exception {
        Workbook wb= new SXSSFWorkbook();
        Sheet sheet = wb.createSheet();
        //属性集
        Field[] fields = objClass.getDeclaredFields();
        //行号
        int r =-1;
        //列数
        int len=0;

        //int len=fieldsInfo.size();
        /**第一行*/

        //r++;
        //Row row = sheet.createRow(r);
        //Cell cell_0 = row.createCell(0);
        //cell_0.setCellValue("订单");
        //for(int c=1;c<len;c++){
        //	Cell cell = row.createCell(c);
        //	cell.setCellValue("");
        //}
        ////合并
        //sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, len-1));
        //CellStyle r0_cellStyle = wb.createCellStyle();
        //r0_cellStyle.setAlignment(HorizontalAlignment.CENTER);
        //
        //Font r0_font = wb.createFont();
        //r0_font.setFontHeightInPoints((short)18);
        //r0_font.setBold(true);
        //r0_cellStyle.setFont(r0_font);
        //cell_0.setCellStyle(r0_cellStyle);

        /**第二行 开始-表格-标题*/

        //样式
        CellStyle r2_cellStyle = wb.createCellStyle();
        r2_cellStyle.setAlignment(HorizontalAlignment.CENTER);
        r2_cellStyle.setWrapText(true);
        r2_cellStyle.setBorderLeft(BorderStyle.THIN);
        r2_cellStyle.setBorderBottom(BorderStyle.THIN);
        r2_cellStyle.setBorderRight(BorderStyle.THIN);
        r2_cellStyle.setBorderTop(BorderStyle.THIN);
        Font r2_font = wb.createFont();
        short titleSize =Short.parseShort(printConfigObj.getInteger("titleSize")+"");
        r2_font.setFontHeightInPoints(titleSize);
        r2_font.setBold(true);
        r2_cellStyle.setFont(r2_font);

        CellStyle r3_cellStyle2 = wb.createCellStyle();

        r3_cellStyle2.setBorderLeft(BorderStyle.THIN);
        r3_cellStyle2.setBorderBottom(BorderStyle.THIN);
        r3_cellStyle2.setBorderRight(BorderStyle.THIN);
        r3_cellStyle2.setBorderTop(BorderStyle.THIN);
        r3_cellStyle2.setAlignment(HorizontalAlignment.CENTER);
        Font r3_font = wb.createFont();
        short bodySize =Short.parseShort(printConfigObj.getInteger("bodySize")+"");
        r3_font.setFontHeightInPoints(bodySize);
        r3_cellStyle2.setFont(r3_font);

        r++;
        int c=0;
        Row row2 = sheet.createRow(r);
        /**标题行*/
        for (Field field : fields) {
            //是需要导出Excel的
            boolean annotationPresent = field.isAnnotationPresent(Excel.class);
            if (annotationPresent) {
                Cell cell = row2.createCell(c);
                // 获取注解值
                String title = field.getAnnotation(Excel.class).name();
                cell.setCellValue(title);
                cell.setCellStyle(r2_cellStyle);
                c++;
            }
        }
        len=c;

        /**第三行 开始-表格-对应值*/

        for (Object orderInfo : pageList) {
            r++;
            c=0;
            Row row3 = sheet.createRow(r);
            for (Field field : fields) {
                //是需要导出Excel的
                boolean annotationPresent = field.isAnnotationPresent(Excel.class);
                if (annotationPresent) {
                    Cell cell = row3.createCell(c);

                    String key=field.getName();
                    String name = key.substring(0, 1).toUpperCase() + key.substring(1);
                    String type = field.getGenericType().toString(); // 获取属性的类型
                    Method m = orderInfo.getClass().getMethod("get" + name);
                    if (type.equals("class java.math.BigDecimal")) {
                        BigDecimal value = (BigDecimal)m.invoke(orderInfo);
                        cell.setCellValue(value.intValue()+"");
                    }else if (type.equals("class java.util.Date")) {
                        Date value = (Date)m.invoke(orderInfo);
                        cell.setCellValue(DateUtils.formatDate(value,"yyyyMMdd"));
                    }else{
                        String value = (String) m.invoke(orderInfo); // 调用getter方法获取属性值
                        cell.setCellValue(value);
                    }
                    cell.setCellStyle(r3_cellStyle2);
                    c++;
                }
            }
        }
        return wb;
    }

    public static String PDFprint(File file , JSONObject printObj ) throws Exception {
        PDDocument document = null;
        String rs="ok";
        try {
            String printerName=printObj.getString("printName");
            document = PDDocument.load(file);
            PrinterJob printJob = PrinterJob.getPrinterJob();
            printJob.setJobName(file.getName());
            if (printerName != null) {
                // 查找并设置打印机
                //获得本台电脑连接的所有打印机
                PrintService[] printServices = PrinterJob.lookupPrintServices();
                if(printServices == null || printServices.length == 0) {
                    System.out.print("打印失败，未找到可用打印机，请检查。");
                    rs="打印失败，未找到可用打印机，请检查。";
                    return rs;
                }
                PrintService printService = null;
                //匹配指定打印机
                for (int i = 0;i < printServices.length; i++) {
                    System.out.println(printServices[i].getName());
                    if (printServices[i].getName().contains(printerName)) {
                        printService = printServices[i];
                        break;
                    }
                }
                if(printService!=null){
                    printJob.setPrintService(printService);
                }else{
                    System.out.print("打印失败，未找到名称为" + printerName + "的打印机，请检查。");
                    rs="打印失败，未找到名称为" + printerName + "的打印机，请检查。";
                    return rs;
                }
            }
            //设置纸张及缩放
            PDFPrintable pdfPrintable = new PDFPrintable(document, Scaling.ACTUAL_SIZE);
            //设置多页打印
            Book book = new Book();
            PageFormat pageFormat = new PageFormat();
            //设置打印方向
            String printDirectionItem = printObj.getString("printDirectionItem");
            if("1".equals(printDirectionItem)){
                pageFormat.setOrientation(PageFormat.PORTRAIT);//纵向  REVERSE_LANDSCAPE 横向
            }else{
                pageFormat.setOrientation(PageFormat.REVERSE_LANDSCAPE);//纵向  REVERSE_LANDSCAPE 横向
            }
            pageFormat.setPaper(getPaper(printObj));//设置纸张
            book.append(pdfPrintable, pageFormat, document.getNumberOfPages());
            printJob.setPageable(book);

            Integer printNum = printObj.getInteger("printNum");
            if(null == printNum){
                printNum=1;
            }
            printJob.setCopies(printNum);//设置打印份数
            //添加打印属性
            HashPrintRequestAttributeSet pars = new HashPrintRequestAttributeSet();
            //是否双面
            Integer printIsDouble = printObj.getInteger("printIsDouble");
            if(null == printIsDouble){
                printIsDouble=0;
            }
            if(printIsDouble == 1){
                pars.add(Sides.DUPLEX); //设置单双页
            }else {
                pars.add(Sides.ONE_SIDED); //设置单双页

            }
            //boolean b = printJob.printDialog(pars);
            //if(b){
                printJob.print(pars);
            //}
        }finally {
            if (document != null) {
                try {
                    document.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return rs;
    }
    public static String PDFprint(PDDocument document, String fileName, JSONObject printObj ) throws Exception {
        String rs="ok";
        try {
            String printerName=printObj.getString("printName");
            PrinterJob printJob = PrinterJob.getPrinterJob();
            printJob.setJobName(fileName);
            if (printerName != null) {
                // 查找并设置打印机
                //获得本台电脑连接的所有打印机
                PrintService[] printServices = PrinterJob.lookupPrintServices();
                if(printServices == null || printServices.length == 0) {
                    System.out.print("打印失败，未找到可用打印机，请检查。");
                    rs="打印失败，未找到可用打印机，请检查。";
                    return rs;
                }
                PrintService printService = null;
                //匹配指定打印机
                for (int i = 0;i < printServices.length; i++) {
                    System.out.println(printServices[i].getName());
                    if (printServices[i].getName().contains(printerName)) {
                        printService = printServices[i];
                        break;
                    }
                }
                if(printService!=null){
                    printJob.setPrintService(printService);
                }else{
                    System.out.print("打印失败，未找到名称为" + printerName + "的打印机，请检查。");
                    rs="打印失败，未找到名称为" + printerName + "的打印机，请检查。";
                    return rs;
                }
            }
            //设置纸张及缩放
            PDFPrintable pdfPrintable = new PDFPrintable(document, Scaling.ACTUAL_SIZE);
            //设置多页打印
            Book book = new Book();
            PageFormat pageFormat = new PageFormat();
            //设置打印方向
            String printDirectionItem = printObj.getString("printDirectionItem");
            if("1".equals(printDirectionItem)){
                pageFormat.setOrientation(PageFormat.PORTRAIT);//纵向  REVERSE_LANDSCAPE 横向
            }else{
                pageFormat.setOrientation(PageFormat.REVERSE_LANDSCAPE);//纵向  REVERSE_LANDSCAPE 横向
            }
            pageFormat.setPaper(getPaper(printObj));//设置纸张
            book.append(pdfPrintable, pageFormat, document.getNumberOfPages());
            printJob.setPageable(book);

            Integer printNum = printObj.getInteger("printNum");
            if(null == printNum){
                printNum=1;
            }
            printJob.setCopies(printNum);//设置打印份数
            //添加打印属性
            HashPrintRequestAttributeSet pars = new HashPrintRequestAttributeSet();
            //是否双面
            Integer printIsDouble = printObj.getInteger("printIsDouble");
            if(null == printIsDouble){
                printIsDouble=0;
            }
            if(printIsDouble == 1){
                pars.add(Sides.DUPLEX); //设置单双页
            }else {
                pars.add(Sides.ONE_SIDED); //设置单双页

            }
            boolean b = printJob.printDialog(pars);
            if(b){
                printJob.print(pars);
            }
        }finally {
            if (document != null) {
                try {
                    document.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return rs;
    }
    public static Paper getPaper(JSONObject printObj) {

        Paper paper = new Paper();

        JSONObject paperSize = getPaperSize(printObj);
        Integer marginLeft = paperSize.getInteger("marginLeft");
        Integer marginRight = paperSize.getInteger("marginRight");
        Integer marginTop = paperSize.getInteger("marginTop");
        Integer marginBottom = paperSize.getInteger("marginBottom");
        Integer width = paperSize.getInteger("width");
        Integer height = paperSize.getInteger("height");

        // 设置边距，单位是像素，10mm边距，对应 28px
        paper.setSize(width, height);
        // 下面一行代码，解决了打印内容为空的问题
        paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom));
        return paper;
    }

    public static JSONObject getPaperSize(JSONObject printObj){
        String printPageType = printObj.getString("printPageType");
        Integer marginLeft = printObj.getInteger("printLeft");
        Integer marginRight = printObj.getInteger("printRight");
        Integer marginTop = printObj.getInteger("printTop");
        Integer marginBottom = printObj.getInteger("printBottom");
        Integer printPageWidth = printObj.getInteger("printPageWidth");
        Integer printPageHeight = printObj.getInteger("printPageHeight");

        if(null == printPageType){
            printPageType="a4";
        }
        if(null == marginLeft){
            marginLeft=0;
        }
        if(null == marginRight){
            marginRight=0;
        }
        if(null == marginTop){
            marginTop=0;
        }
        if(null == marginBottom){
            marginBottom=0;
        }

        if( "a4".equals(printPageType.toLowerCase())){
            //210 *297
            printPageWidth=210;
            printPageHeight=297;
        } else{
            if(null == printPageWidth){
                printPageWidth=210;
            }
            if(null == printPageHeight){
                printPageHeight=297;
            }
        }

        // 像素=规格×当前分辨率/2.54  默认为A4纸张，分辨率为72时 对应像素宽和高分别为 595, 842 规格单位是毫米 则除10

        BigDecimal px=new BigDecimal(72/2.54/10);
        int width = px.multiply(new BigDecimal(printPageWidth)).setScale(0, BigDecimal.ROUND_HALF_DOWN).intValue();
        int height = px.multiply(new BigDecimal(printPageHeight)).setScale(0, BigDecimal.ROUND_HALF_DOWN).intValue();

        //设置打印方向
        String printDirectionItem = printObj.getString("printDirectionItem");
        if(null == printDirectionItem){
            printDirectionItem="1";
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("width",width);
        jsonObject.put("height",height);

        jsonObject.put("marginLeft",marginLeft);
        jsonObject.put("marginRight",marginRight);
        jsonObject.put("marginTop",marginTop);
        jsonObject.put("marginBottom",marginBottom);
        jsonObject.put("direction",printDirectionItem);


        return jsonObject;
    }
}
